package com.yf.web.config;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import io.swagger.annotations.ApiOperation;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 考试系统接口配置
 * @author bool
 * @date 2020/8/19 20:53
 */
@Configuration
@EnableSwagger2
@ConfigurationProperties(prefix = "swagger")
public class SwaggerConfig {


    @Bean
    public Docket commonApi() {
        return buildDocket("公共模块接口", tokenSchema(), "/api/common/**");
    }

    @Bean
    public Docket certApi() {
        return buildDocket("证书模块接口", tokenSchema(), "/api/cert/**");
    }

    @Bean
    public Docket courseApi() {
        return buildDocket("课程模块接口", tokenSchema(), "/api/course/**");
    }

    @Bean
    public Docket examApi() {
        return buildDocket("考试模块接口", tokenSchema(), "/api/exam/**", "/api/qu/**", "/api/train/**", "/api/tmpl/**", "/api/paper/**");
    }

    @Bean
    public Docket battleApi() {
        return buildDocket("知识竞赛模块接口", tokenSchema(), "/api/battle/**");
    }


    @Bean
    public Docket sysApi() {
        return buildDocket("系统模块接口", tokenSchema(), "/api/sys/**");
    }


    @Bean
    public Docket connect() {
        return buildDocket("三方登录连接", null, "/api/connect/**");
    }


    @Bean
    public Docket openAPI() {
        return buildDocket("开放数据接口", accessSchema(), "/api/open/**");
    }

    @Bean
    public Docket openApiAI() {
        return buildDocket("openAI试题开放数据接口", accessSchema(), "/api/openAI/qu/qu/**");
    }

    @Bean
    public Docket openRepAI() {
        return buildDocket("openAI题库开放数据接口", accessSchema(), "/api/openAI/repo/**");
    }

    @Bean
    public Docket openTemAI() {
        return buildDocket("openAI试卷开放数据接口", accessSchema(), "/api/openAI/tmpl/tmpl/**");
    }

    @Bean
    public Docket openClassAI() {
        return buildDocket("openAI课程开放数据接口", accessSchema(), "/api/openAI/course/course/**");
    }

    @Bean
    public Docket openExamAI() {
        return buildDocket("openAI考试开放数据接口", accessSchema(), "/api/openAI/exam/exam/**");
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title("考试系统接口")
                .description("考试系统接口，包含了需要用户登录的接口及通过授权获取数据的开放接口")
                .contact(new Contact("Gmc", "https://exameihelip.c2.eplus.org.cn/", "gmcstudent@163.com"))
                .version("6.0.0")
                .build();
    }


    /**
     * 结构接口分组
     *
     * @param title
     * @param scheme
     * @param paths
     * @return
     */
    public Docket buildDocket(String title, SecurityScheme scheme, String... paths) {

        // 接口规则
        Predicate<String> predicate;
        if (paths.length == 1) {
            predicate = PathSelectors.ant(paths[0]);
        } else {
            List<Predicate<String>> list = new ArrayList<>();
            for (String path : paths) {
                list.add(PathSelectors.ant(path));
            }
            predicate = Predicates.or(list);
        }

        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName(title)
                .select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(predicate)
                .build();

        if (scheme!=null) {
            docket.securitySchemes(Collections.singletonList(scheme))
                    .securityContexts(securityContexts());
        }

        return docket;
    }


    @Bean
    SecurityScheme tokenSchema() {
        return new ApiKey("token", "token", "header");
    }

    @Bean
    SecurityScheme accessSchema() {
        return new ApiKey("access", "access", "header");
    }


    private List securityContexts() {
        List securityContexts = new ArrayList<>();
        securityContexts.add(SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.any()).build());
        return securityContexts;
    }

    private List defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("access", authorizationScopes));
        securityReferences.add(new SecurityReference("token", authorizationScopes));
        return securityReferences;
    }

}
